<template>
  <div class="typescript-advanced-demo">
    <h1>Vue 3 TypeScript 高级用法演示</h1>
    
    <div class="demo-section">
      <h2>1. 组件Props类型定义</h2>
      <div class="demo-content">
        <props-demo 
          :user-data="userData"
          :is-active="isActive"
          @status-change="handleStatusChange"
        />
      </div>
      <CodeBlock code="组件Props类型定义" language="typescript">
        {{ propsTypeCode }}
      </CodeBlock>
    </div>

    <div class="demo-section">
      <h2>2. 组合式API类型推断</h2>
      <div class="demo-content">
        <div class="inference-example">
          <h3>响应式对象类型推断</h3>
          <div class="user-info">
            <p>姓名: {{ inferredUser.name }}</p>
            <p>年龄: {{ inferredUser.age }}</p>
            <p>角色: {{ inferredUser.role }}</p>
          </div>
          <button @click="updateInferredUser" class="btn-primary">更新用户信息</button>
        </div>
      </div>
      <CodeBlock code="组合式API类型推断" language="typescript">
        {{ inferenceCode }}
      </CodeBlock>
    </div>

    <div class="demo-section">
      <h2>3. 泛型组件</h2>
      <div class="demo-content">
        <generic-list 
          :items="users" 
          :render-item="renderUserItem"
        />
        <generic-list 
          :items="products" 
          :render-item="renderProductItem"
        />
      </div>
      <CodeBlock code="泛型组件实现" language="typescript">
        {{ genericComponentCode }}
      </CodeBlock>
    </div>

    <div class="demo-section">
      <h2>4. 类型守卫和断言</h2>
      <div class="demo-content">
        <div class="type-guard-example">
          <button @click="processUnknownData" class="btn-primary">处理未知数据</button>
          <div v-if="processedResult" class="result-box">
            <h3>处理结果:</h3>
            <CodeBlock :code="processedResult" language="typescript"></CodeBlock>
          </div>
        </div>
      </div>
      <CodeBlock code="类型守卫和断言" language="typescript">
        {{ typeGuardCode }}
      </CodeBlock>
    </div>

    <div class="demo-section">
      <h2>5. 模块扩展和声明合并</h2>
      <div class="demo-content">
        <div class="extension-example">
          <p>当前环境: {{ envInfo.environment }}</p>
          <p>API基础URL: {{ envInfo.apiBaseUrl }}</p>
          <p>应用版本: {{ envInfo.appVersion }}</p>
        </div>
      </div>
      <CodeBlock code="模块扩展和声明合并" language="typescript">
        {{ moduleExtensionCode }}
      </CodeBlock>
    </div>

    <div class="demo-section">
      <h2>6. 高级组合式函数类型</h2>
      <div class="demo-content">
        <div class="composable-example">
          <h3>防抖搜索示例</h3>
          <input 
            v-model="searchQuery"
            type="text"
            placeholder="输入搜索内容..."
            class="search-input"
          />
          <div v-if="searchResults.length > 0" class="search-results">
            <div v-for="result in searchResults" :key="result.id" class="search-item">
              {{ result.text }}
            </div>
          </div>
          <div v-else-if="searchQuery" class="no-results">
            没有找到结果
          </div>
        </div>
      </div>
      <CodeBlock code="高级组合式函数类型" language="typescript">
        {{ composableTypeCode }}
      </CodeBlock>
    </div>

    <div class="best-practices">
      <h2>Vue 3 + TypeScript 最佳实践</h2>
      <ul>
        <li><strong>使用 defineProps 和 defineEmits</strong>: 利用 Vue 3 的编译器宏获取完整的类型推断</li>
        <li><strong>避免使用 any</strong>: 尽可能为所有变量提供明确的类型定义</li>
        <li><strong>使用 TypeScript 装饰器</strong>: 对于高级场景，可以使用装饰器增强类型系统</li>
        <li><strong>创建类型工具</strong>: 为常用的类型模式创建可重用的类型工具</li>
        <li><strong>使用泛型组件</strong>: 提高组件的复用性和类型安全性</li>
        <li><strong>编写类型测试</strong>: 使用 dtslint 或其他工具验证类型定义</li>
      </ul>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, reactive, computed, defineComponent, PropType } from 'vue'
import CodeBlock from '@components/CodeBlock.vue'

// 演示数据
const userData = reactive({
  id: 1,
  name: '张三',
  email: 'zhangsan@example.com',
  role: 'admin'
})

const isActive = ref(true)

// 推断类型的用户对象
const inferredUser = reactive({
  name: '李四',
  age: 30,
  role: 'user' as const
})

// 列表数据
const users = [
  { id: 1, name: '张三', email: 'zhangsan@example.com' },
  { id: 2, name: '李四', email: 'lisi@example.com' },
  { id: 3, name: '王五', email: 'wangwu@example.com' }
]

const products = [
  { id: 101, title: '产品A', price: 99.99 },
  { id: 102, title: '产品B', price: 199.99 },
  { id: 103, title: '产品C', price: 299.99 }
]

// 搜索相关
const searchQuery = ref('')
const searchResults = ref<Array<{id: number; text: string}>>([])

// 处理结果
const processedResult = ref<string | null>(null)

// 环境信息
const envInfo = {
  environment: 'development',
  apiBaseUrl: 'http://localhost:3000/api',
  appVersion: '1.0.0',
  features: {
    analytics: true,
    notifications: true
  }
}

// 代码示例
const propsTypeCode = `
// 组件Props类型定义示例
interface User {
  id: number;
  name: string;
  email: string;
  role: 'admin' | 'user' | 'guest';
}

const props = defineProps<{
  userData: User;
  isActive: boolean;
  optionalMessage?: string;
}>()

const emit = defineEmits<{
  'status-change': [active: boolean];
  'update': [data: Partial<User>];
}>()
`

const inferenceCode = `
// 组合式API类型推断
import { ref, reactive, computed } from 'vue'

// reactive 自动推断类型
const user = reactive({
  name: '李四',
  age: 30,
  role: 'user' as const // 使用 as const 锁定字面量类型
})

// computed 自动推断返回类型
const isAdult = computed(() => user.age >= 18)

// 函数参数类型推断
function updateUser(user: typeof user, updates: Partial<typeof user>) {
  Object.assign(user, updates)
}
`

const genericComponentCode = `
// 泛型组件实现
import { defineComponent, PropType } from 'vue'

interface ListProps<T> {
  items: T[];
  renderItem: (item: T, index: number) => JSX.Element;
}

const GenericList = defineComponent({
  name: 'GenericList',
  props: {
    items: {
      type: Array as PropType<any[]>,
      required: true
    },
    renderItem: {
      type: Function as PropType<(item: any, index: number) => JSX.Element>,
      required: true
    }
  },
  setup(props) {
    return () => (
      <div class="generic-list">
        {props.items.map((item, index) => props.renderItem(item, index))}
      </div>
    )
  }
})
`

const typeGuardCode = `
// 类型守卫和断言
interface User {
  id: number;
  name: string;
  email: string;
}

interface Product {
  id: number;
  title: string;
  price: number;
}

// 类型守卫函数
function isUser(data: any): data is User {
  return (
    typeof data === 'object' && 
    data !== null &&
    'id' in data && 
    'name' in data && 
    'email' in data
  )
}

function isProduct(data: any): data is Product {
  return (
    typeof data === 'object' && 
    data !== null &&
    'id' in data && 
    'title' in data && 
    'price' in data
  )
}

// 处理未知数据
function processData(data: unknown) {
  if (isUser(data)) {
    return '用户: ' + data.name + ', 邮箱: ' + data.email;
  } else if (isProduct(data)) {
    return '产品: ' + data.title + ', 价格: ' + data.price;
  }
  return '未知数据类型';
}
`

const moduleExtensionCode = `
// 模块扩展和声明合并

// 扩展 Vue 的全局属性
declare module '@vue/runtime-core' {
  interface ComponentCustomProperties {
    $env: {
      environment: string;
      apiBaseUrl: string;
      appVersion: string;
      features: {
        analytics: boolean;
        notifications: boolean;
      }
    }
  }
}

// 声明合并示例
declare interface Window {
  __APP_VERSION__: string;
  __API_BASE_URL__: string;
}

// 类型工具
type DeepReadonly<T> = {
  readonly [P in keyof T]: T[P] extends object ? DeepReadonly<T[P]> : T[P]
}

type PartialDeep<T> = {
  [P in keyof T]?: T[P] extends object ? PartialDeep<T[P]> : T[P]
}
`

const composableTypeCode = `
// 高级组合式函数类型
import { ref, watch, Ref } from 'vue'

// 带泛型的防抖函数
function useDebounce<T>(value: Ref<T>, delay: number = 300): Ref<T> {
  const debouncedValue = ref<T>(value.value)
  
  let timeoutId: ReturnType<typeof setTimeout>
  
  watch(value, (newValue) => {
    clearTimeout(timeoutId)
    timeoutId = setTimeout(() => {
      debouncedValue.value = newValue
    }, delay)
  })
  
  return debouncedValue
}

// 带类型参数的API请求函数
type ApiResponse<T> = {
  data: T;
  success: boolean;
  message?: string;
}

async function useApi<T>(url: string): Promise<ApiResponse<T>> {
  try {
    const response = await fetch(url)
    const data = await response.json()
    return { data, success: true } as ApiResponse<T>
  } catch (error) {
    return {
      data: {} as T,
      success: false,
      message: error instanceof Error ? error.message : 'Unknown error'
    }
  }
}
`

// 事件处理
function handleStatusChange(active: boolean) {
  console.log('状态改变:', active)
  isActive.value = active
}

// 更新推断类型的用户
function updateInferredUser() {
  inferredUser.name = '李四(已更新)'
  inferredUser.age += 1
  // 以下代码会在编译时报错，因为 role 被 as const 锁定为 'user'
  // inferredUser.role = 'admin' // 类型错误
}

// 渲染列表项
function renderUserItem(user, index) {
  return {
    template: `
      <div class="list-item user-item">
        <strong>{{ user.name }}</strong> - {{ user.email }}
      </div>
    `,
    data() {
      return { user }
    }
  }
}

function renderProductItem(product, index) {
  return {
    template: `
      <div class="list-item product-item">
        <strong>{{ product.title }}</strong> - ¥{{ product.price }}
      </div>
    `,
    data() {
      return { product }
    }
  }
}

// 处理未知数据
function processUnknownData() {
  // 模拟随机数据类型
  const dataType = Math.random() > 0.5 ? 'user' : 'product'
  
  let data: unknown
  if (dataType === 'user') {
    data = { id: 1, name: '测试用户', email: 'test@example.com' }
  } else {
    data = { id: 100, title: '测试产品', price: 199.99 }
  }
  
  // 类型守卫
  if (isUser(data)) {
    processedResult.value = `用户: ${data.name}, 邮箱: ${data.email}`
  } else if (isProduct(data)) {
    processedResult.value = `产品: ${data.title}, 价格: ¥${data.price}`
  } else {
    processedResult.value = '未知数据类型'
  }
}

// 类型守卫函数
function isUser(data: any): data is {id: number; name: string; email: string} {
  return (
    typeof data === 'object' && 
    data !== null &&
    'id' in data && 
    'name' in data && 
    'email' in data
  )
}

function isProduct(data: any): data is {id: number; title: string; price: number} {
  return (
    typeof data === 'object' && 
    data !== null &&
    'id' in data && 
    'title' in data && 
    'price' in data
  )
}

// 防抖搜索模拟
let searchTimeout: number | undefined

watch(searchQuery, (newQuery) => {
  clearTimeout(searchTimeout)
  searchTimeout = window.setTimeout(() => {
    if (newQuery.trim()) {
      // 模拟搜索结果
      searchResults.value = [
        { id: 1, text: `搜索结果: ${newQuery} - 1` },
        { id: 2, text: `搜索结果: ${newQuery} - 2` },
        { id: 3, text: `搜索结果: ${newQuery} - 3` }
      ]
    } else {
      searchResults.value = []
    }
  }, 500)
})

// PropsDemo 组件
// 注册全局组件
import { defineComponent } from 'vue'

// PropsDemo 组件定义
const PropsDemo = {
  name: 'PropsDemo',
  props: {
    userData: {
      type: Object,
      required: true
    },
    isActive: {
      type: Boolean,
      default: false
    }
  },
  emits: ['status-change'],
  methods: {
    toggleStatus() {
      this.$emit('status-change', !this.isActive)
    }
  },
  template: `
    <div class="props-demo" :style="{ opacity: isActive ? 1 : 0.6 }">
      <h3>用户信息</h3>
      <p>ID: {{ userData.id }}</p>
      <p>姓名: {{ userData.name }}</p>
      <p>邮箱: {{ userData.email }}</p>
      <p>角色: {{ userData.role }}</p>
      <button @click="toggleStatus" class="btn-secondary">
        {{ isActive ? '禁用' : '启用' }}
      </button>
    </div>
  `
}

// GenericList 组件定义
const GenericList = {
  name: 'GenericList',
  props: {
    items: {
      type: Array,
      required: true
    },
    renderItem: {
      type: Function,
      required: true
    }
  },
  template: `
    <div class="generic-list">
      <div v-for="(item, index) in items" :key="item.id || index">
        <component :is="renderItem(item, index)" />
      </div>
    </div>
  `
}

// 渲染列表项已在前面定义
</script>

<style scoped>
.typescript-advanced-demo {
  padding: 20px;
  max-width: 1200px;
  margin: 0 auto;
}

h1 {
  text-align: center;
  margin-bottom: 40px;
  color: #333;
}

h2 {
  margin-top: 40px;
  margin-bottom: 20px;
  color: #42b883;
  font-size: 1.5rem;
  border-bottom: 2px solid #42b883;
  padding-bottom: 10px;
}

h3 {
  margin-top: 20px;
  margin-bottom: 15px;
  color: #333;
  font-size: 1.2rem;
}

.demo-section {
  margin-bottom: 40px;
  padding: 20px;
  background-color: #f8f9fa;
  border-radius: 8px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

.demo-content {
  background-color: white;
  padding: 20px;
  border-radius: 8px;
  margin-bottom: 20px;
}

.btn-primary {
  background-color: #42b883;
  color: white;
  border: none;
  padding: 10px 20px;
  border-radius: 4px;
  cursor: pointer;
  font-size: 1rem;
  transition: background-color 0.3s;
}

.btn-primary:hover {
  background-color: #35495e;
}

.btn-secondary {
  background-color: #6c757d;
  color: white;
  border: none;
  padding: 8px 16px;
  border-radius: 4px;
  cursor: pointer;
  font-size: 0.9rem;
  transition: background-color 0.3s;
}

.btn-secondary:hover {
  background-color: #5a6268;
}

/* Props Demo 样式 */
.props-demo {
  padding: 20px;
  background-color: #e8f5e9;
  border-radius: 8px;
  transition: opacity 0.3s ease;
}

/* 推断示例样式 */
.inference-example {
  padding: 20px;
  background-color: #e3f2fd;
  border-radius: 8px;
}

.user-info {
  margin-bottom: 15px;
  padding: 15px;
  background-color: white;
  border-radius: 4px;
}

.user-info p {
  margin: 8px 0;
}

/* 泛型列表样式 */
.generic-list {
  margin-bottom: 20px;
}

.list-item {
  padding: 15px;
  margin-bottom: 10px;
  border-radius: 4px;
  transition: transform 0.2s ease;
}

.list-item:hover {
  transform: translateY(-2px);
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}

.user-item {
  background-color: #e8f5e9;
}

.product-item {
  background-color: #fff3e0;
}

/* 类型守卫示例样式 */
.type-guard-example {
  padding: 20px;
  background-color: #fce4ec;
  border-radius: 8px;
}

.result-box {
  margin-top: 20px;
  padding: 15px;
  background-color: white;
  border-radius: 4px;
  border-left: 4px solid #42b883;
}

.result-box pre {
  white-space: pre-wrap;
  word-break: break-word;
}

/* 模块扩展示例样式 */
.extension-example {
  padding: 20px;
  background-color: #f3e5f5;
  border-radius: 8px;
}

.extension-example p {
  margin: 8px 0;
  padding: 8px;
  background-color: white;
  border-radius: 4px;
}

/* 组合式函数示例样式 */
.composable-example {
  padding: 20px;
  background-color: #fffde7;
  border-radius: 8px;
}

.search-input {
  width: 100%;
  padding: 10px;
  border: 1px solid #ddd;
  border-radius: 4px;
  font-size: 1rem;
  margin-bottom: 15px;
}

.search-results {
  max-height: 300px;
  overflow-y: auto;
}

.search-item {
  padding: 10px;
  background-color: white;
  border-bottom: 1px solid #eee;
  cursor: pointer;
  transition: background-color 0.2s;
}

.search-item:hover {
  background-color: #f5f5f5;
}

.no-results {
  padding: 20px;
  text-align: center;
  color: #666;
  background-color: white;
  border-radius: 4px;
}

/* 最佳实践样式 */
.best-practices {
  margin-top: 40px;
  padding: 20px;
  background-color: #e3f2fd;
  border-radius: 8px;
}

.best-practices ul {
  padding-left: 20px;
}

.best-practices li {
  margin-bottom: 10px;
  line-height: 1.6;
}

.best-practices strong {
  color: #1976d2;
}

@media (max-width: 768px) {
  .demo-section {
    padding: 15px;
  }
  
  .demo-content {
    padding: 15px;
  }
  
  h1 {
    font-size: 1.8rem;
  }
  
  h2 {
    font-size: 1.3rem;
  }
}
</style>